//
// Created by mio on 25-4-20.
//
#include "amf.h"
#include "../Net/BufferReader.h"
#include "../Net/BufferWriter.h"

#include <cstring>



int AmfDecoder::decode(const char* data, int size, int n)
{
    int bytes_used = 0;
    // 循环解码，直到数据耗尽或达到解码次数限制 n
    while (bytes_used < size)
    {
        // 读取 1 字节的类型标记
        char type = data[bytes_used];
        bytes_used += 1;
        int ret = 0;
        switch (type)
        {
        case AMF_NUMBER:
            m_obj.type = AMF_NUMBER;
            ret = decodeNumber(data + bytes_used, size - bytes_used, m_obj.amf_number);
            break;
        case AMF_BOOLEAN:
            m_obj.type = AMF_BOOLEAN;
            ret = decodeBoolean(data + bytes_used, size - bytes_used, m_obj.amf_boolean);
            break;
        case AMF_STRING:
            m_obj.type = AMF_STRING;
            ret = decodeString(data + bytes_used, size - bytes_used, m_obj.amf_string);
            break;
        case AMF0_OBJECT:
            ret = decodeObject(data + bytes_used, size - bytes_used, m_objs);
            break;
        case AMF0_ECMA_ARRAY:
            // AMF0 ECMA Array 前面有 4 字节的 count 字段，这里简单跳过它
            // 然后当作普通 Object 来解码键值对
            ret = decodeObject(data + bytes_used + 4, size - bytes_used - 4, m_objs);
        default:
            break;
        }

        if (ret < 0) break;
        bytes_used += ret;
        n--;
        if (n == 0) break; // 解码次数
    }
    return bytes_used;
}

/**
 * @brief 解码 AMF0 Boolean。
 * @param data 指向布尔值字节 (0x00 或 0x01)。
 * @param size 剩余数据大小。
 * @param amf_boolean 输出参数，存储解码结果。
 * @return int 消耗的字节数 (1)。如果 size 不足返回 0。
 */
int AmfDecoder::decodeBoolean(const char* data, int size, bool& amf_boolean)
{
    if (size < 1) return 0;
    amf_boolean = (data[0] != 0);
    return 1;
}


int AmfDecoder::decodeNumber(const char* data, int size, double& amf_number)
{
    if (size < 8) return 0;  // double
    char* ch_in = (char*) data;
    char* ch_out = (char*)&amf_number;

    /* 大小端转换 */
    ch_out[0] = ch_in[7];
    ch_out[1] = ch_in[6];
    ch_out[2] = ch_in[5];
    ch_out[3] = ch_in[4];
    ch_out[4] = ch_in[3];
    ch_out[5] = ch_in[2];
    ch_out[6] = ch_in[1];
    ch_out[7] = ch_in[0];

    return 8;
}

int AmfDecoder::decodeString(const char* data, int size, std::string& amf_string)
{
    if (size < 2) return 0; // string 在AMF中2字节

    int byte_used = 0;
    // 获取大小
    int strSize = decodeInt16(data, size);
    byte_used += 2;
    // 获取string
    if (strSize > (size - byte_used)) return -1; // 数据不全
    amf_string = std::string(&data[byte_used], 0, strSize);
    byte_used += strSize;
    return byte_used;
}

int AmfDecoder::decodeObject(const char* data, int size, AmfObjects& amf_objs)
{
    amf_objs.clear();
    int bytes_used = 0;
    // 循环解码键值对
    while (size > 0)
    {
        int strLen = decodeInt16(data + bytes_used, size); // 获取字符串长度
        size -= 2;
        // 检查是否有足够数据读取整个 Key
        if (size < strLen) return bytes_used; // 说明数据不完整

        /* 获取键 */
        std::string key(data + bytes_used + 2, 0, strLen);
        size -= strLen;

        /* 获取对象 */
        AmfDecoder dec; // 先创建解码对象
        int ret = dec.decode(data + bytes_used + 2 + strLen, size, 1); //每次解码一个对象 返回值就是消耗多少字节数
        bytes_used += 2 + strLen + ret;
        if (ret <= 1) break;

        /* 插入键值 */
        amf_objs.emplace(key, dec.getObject());
    }
    return bytes_used;
}

uint16_t AmfDecoder::decodeInt16(const char* data, int size)
{
    return ReadUint16BE((char*)data);
}

uint32_t AmfDecoder::decodeInt24(const char* data, int size)
{
    return ReadUint24BE((char*)data);
}

uint32_t AmfDecoder::decodeInt32(const char* data, int size)
{
    return ReadUint32BE((char*)data);
}

AmfEncoder::AmfEncoder(uint32_t size) :
    m_data(new char[size], std::default_delete<char[]>()),
    m_size(size)
{
    // m_data = std::make_shared<char>(); 会破坏堆内存, 导致TcpServer中的connections内部指针被修改, 进而在后续的客户端断开连接时访问修改后的内存导致整个服务器崩溃
}

AmfEncoder::~AmfEncoder()
{
}

void AmfEncoder::encodeString(const char* str, int len, bool isObject)
{
    if ((m_size - m_index) < (len + 1 + 2 + 2)) // 当前内存剩余空间不足
    {
        this->realloc(m_size + len + 5); // 扩容
    }

    /* 根据长度选择 String 或 Long String */
    if (len < 65536)    // amf0_string
    {
        if (isObject)
        {
            m_data.get()[m_index++] = AMF0_STRING; //将类型赋值
        }
        encodeInt16(len); // 编码长度 1字节类型 + 2长度 + 具体数值(string number bool)
    }
    else                // amf0_long_string
    {
        if (isObject)
        {
            m_data.get()[m_index++] = AMF0_LONG_STRING;
        }
        encodeInt32(len);
    }
    memcpy(m_data.get() + m_index, str, len);
    m_index += len;

}

void AmfEncoder::encodeNumber(double value)
{
    if ((m_size - m_index) < 9)     // 1字节类型 8字节double
    {
        this->realloc(m_size + 1024);
    }
    // 写入 Number 类型标记
    m_data.get()[m_index++] = AMF0_NUMBER;

    // 写入数据
    char* ch_in = (char*)&value;
    char* ch_out = m_data.get();
    // 赋值 小端到大端转换
    ch_out[m_index++] = ch_in[7];   // 低地址写高字节
    ch_out[m_index++] = ch_in[6];
    ch_out[m_index++] = ch_in[5];
    ch_out[m_index++] = ch_in[4];
    ch_out[m_index++] = ch_in[3];
    ch_out[m_index++] = ch_in[2];
    ch_out[m_index++] = ch_in[1];
    ch_out[m_index++] = ch_in[0];   // 高地址写低字节
}

void AmfEncoder::encodeBoolean(int value)
{
    if ((m_size - m_index) < 2) // 1字节类型 bool 1字节
    {
        this->realloc(m_size + 1024);
    }
    m_data.get()[m_index++] = AMF0_BOOLEAN;
    m_data.get()[m_index++] = value ? 0x01 : 0x00;
}

void AmfEncoder::encodeObjects(AmfObjects& objs)
{
    if (objs.size() == 0) // 对象为空
    {
        encodeInt8(AMF0_NULL);
        return;
    }
    // 写入 Object 类型标记
    encodeInt8(AMF0_OBJECT);
    // 遍历 Map 中的键值对
    for (auto it : objs) // 遍历编码 键->string, 值->对象
    {
        // 编码 Key (字符串，不带类型标记 isObject=false)
        encodeString(it.first.c_str(), (int)it.first.size(), false);
        switch (it.second.type)
        {
        case AMF_NUMBER:
            encodeNumber(it.second.amf_number);
            break;
        case AMF_STRING:
            encodeString(it.second.amf_string.c_str(), (int)it.second.amf_string.size());
            break;
        case AMF_BOOLEAN:
            encodeBoolean(it.second.amf_boolean);
            break;
        default:
            break;
        }
    }

    // 结尾
    encodeString("", 0, false);
    encodeInt8(AMF0_OBJECT_END);
}

void AmfEncoder::encodeECMA(AmfObjects& objs)
{
    encodeInt8(AMF0_ECMA_ARRAY);
    encodeInt32(0);
    for (auto it : objs) // 遍历编码 键->string, 值->对象
    {
        encodeString(it.first.c_str(), (int)it.first.size(), false);
        switch (it.second.type)
        {
        case AMF_NUMBER:
            encodeNumber(it.second.amf_number);
            break;
        case AMF_STRING:
            encodeString(it.second.amf_string.c_str(), (int)it.second.amf_string.size());
            break;
        case AMF_BOOLEAN:
            encodeBoolean(it.second.amf_boolean);
            break;
        default:
            break;
        }
    }

    // 结尾
    encodeString("", 0, false);

    encodeInt8(AMF0_OBJECT_END);    // End 标记
}

void AmfEncoder::encodeInt8(int8_t value)
{
    if ((m_size - m_index) < 1)
    {
        this->realloc(m_size + 1024);
    }
    m_data.get()[m_index++] = value;
}

void AmfEncoder::encodeInt16(int16_t value)
{
    if ((m_size - m_index) < 2)
    {
        this->realloc(m_size + 1024);
    }
    WriteUint16BE(m_data.get() + m_index, value);
    m_index += 2;
}

void AmfEncoder::encodeInt24(int32_t value)
{
    if ((m_size - m_index) < 3)
    {
        this->realloc(m_size + 1024);
    }
    WriteUint24BE(m_data.get() + m_index, value);
    m_index += 3;
}

void AmfEncoder::encodeInt32(int32_t value)
{
    if ((m_size - m_index) < 4)
    {
        this->realloc(m_size + 1024);
    }
    WriteUint32BE(m_data.get() + m_index, value);
    m_index += 4;
}

void AmfEncoder::realloc(uint32_t size)
{
    if (size <= m_size) return;
    std::shared_ptr<char> data(new char[size], std::default_delete<char[]>());
    memcpy(data.get(), m_data.get(),m_index);
    m_size = size;
    m_data = data;
}
